﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace SqliteDriver
{
	/*
		Created just to break up the large driver class. This will take care of all the 
		commands that generate code or show or search SQL source
	*/ 
	class SourcecodeCommandProcessor
	{
		internal SourcecodeCommandProcessor(SqliteDataSource parent)
		{
			this.dataSource = parent;
		}

		internal String ProcessCommand(DbView.Command command)
		{
			// Command should contain a parameter
			String param = DbView.Command.TableParameterName(0);
			String objectName = command[param]; // view ?

			// [Specialise: override display text generation ]
			if (command.Cmd == DbView.Commands.Cmnd.TableSource) // they want the create table command
				return this.ScriptTable(this.dataSource, this.TableFromCommand(command));

			
			if (command.Cmd == DbView.Commands.Cmnd.ShowSource)  // generic constion
			{
				// assume we get a hint from the parameters
				if (command["TYPE"] == "DATA")
				{
					String tableName = command["TABLE"];
					// overwrite the official place for the object
					command.AddParam(DbView.Command.TableParameterName(0), tableName);
					return this.ScriptData(this.dataSource, tableName);
				}
				//if (command["TYPE"] == "FK")
				//{
				//    return this.ScriptForeignKeys(this.dataSource, objectName, false, false);
				//}
				//if (command["TYPE"] == "FKALL")
				//{
				//    return this.ScriptForeignKeys(this.dataSource, objectName, true, false);
				//}
				//if (command["TYPE"] == "XFK")
				//{
				//    return this.ScriptForeignKeys(this.dataSource, objectName, false, true);
				//}
				//if (command["TYPE"] == "XFKALL")
				//{
				//    return this.ScriptForeignKeys(this.dataSource, objectName, true, true);
				//}
			}

			// default / original look in syscomments
			String sourceCode = Helper.GetSourceCode(this.dataSource.ConnectionString, objectName);
			return sourceCode;
		}

		private string TableFromCommand(DbView.Command command)
		{
			if (command["TABLE"] != null)
				return command["TABLE"];
			return command[DbView.Command.TableParameterName(0)];
		}

		// Queries database for source of Views, Stored procedures, Triggers etc.
		internal String GetSourceCode(DbView.ViewContext context, String objectName)
		{
			//String objectName = context.ViewDef.TableName;
			String sourceCode = Helper.GetSourceCode(this.dataSource.ConnectionString, objectName);
			return sourceCode;
		}
		// Searches the source of Views, Stored procedures, Triggers etc. for the search text held in the context
		internal string SearchSourceCommand(DbView.ViewContext context)
		{
		    String searchText = context.Command["SEARCH"]; // what to search ffor
		    String filter = context.FilterString;          // what to filter object names on (rarely used?)
		    String template = SqliteTemplates.Templates.FetchTemplate(this.dataSource.SqlVersion, context.Command.Cmd);
		    // replace search string using the 
		    template = SqliteTemplates.Templates.ProcessFilterClause(template, "{", searchText);
		    template = SqliteTemplates.Templates.ProcessFilterClause(template, filter);
		    String commandString = String.Format(template, searchText.Replace("'", "''")); // A bit hacky considering there is a mechanism for handling text search
		    return commandString;
		}

		/////////////////////////////////////////////////////////////////////////
		// helpers
		private String ScriptTable(DbViewDriver.IDataSource source, String tableName)
		{
			SqlTableSchema schema = this.dataSource.MakeSchemaFor(tableName);
			SqlServerScripter scripter = new SqlServerScripter(tableName, schema);
			return scripter.ScriptCreateTable();
		}

		// Inherited from SQL Server
		//private String ScriptForeignKeys(DbViewDriver.IDataSource source, String tableName, bool allTables, bool dropOnly)
		//{
		//    String commandTemplate = SqliteTemplates.Templates.FetchTemplate(this.dataSource.SqlVersion, DbView.Commands.Cmnd.ForeignKeys);
		//    String sql = TableCommandProcessor.AddFilterClause(commandTemplate, "", this.dataSource.IsCaseSensitive);
		//    DataSet dataset = new DataSet();
		//    Helper.GenericMakeDset(this.dataSource.ConnectionString, sql, tableName, out dataset);
		//    FkScripter scripter = new FkScripter();
		//    scripter.ConfigureTable( dataset.Tables[0], 0, 4, 1, 2, 3); // Sorry
		//    scripter.DisabledCol = 5;
		//    scripter.DeleteActionCol = 7;
		//    scripter.UpdateActionCol = 8;
		//    scripter.ReplicationCol = 9;
		//    String script = scripter.ScriptKeys(tableName, allTables, dropOnly);
		//    return script;
		//}

		private String ScriptData(DbViewDriver.IDataSource source, String tableName)
		{
			SqlTableSchema schema = this.dataSource.MakeSchemaFor(tableName);
			SqlServerScripter scripter = new SqlServerScripter(tableName, schema);
			DataSet dataset = new DataSet();
			Helper.GenericMakeDset(this.dataSource.ConnectionString, "select * from "+tableName, tableName, out dataset);
			DataTable dataTable = dataset.Tables[0];
			
			return scripter.ScriptData(dataTable);
		}
		
		SqliteDataSource dataSource;

		const String NO_SOURCE_CODE = @"
/*
	Could not find source for {0}.

	This is either because the object does not exist in the database or the connection
	you are using does not have permission to access the source.
*/
";
		const String NO_PERMISSION_TO_SOURCE_CODE = @"
/*
	Could not access source for {0}.

	A quick check indicates that the current connection does not have
	VIEW DEFINITION permission, which the programm requires for any operations
	that involve examining or reporting view, stored procedure, function etc 
	source code. 
*/
";
	}
}
